package org.mch.comm.http;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.io.IOUtils;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.mch.biz.handle.AbstractHandler;

/**
 * 描述：Http Request请求处理器；<BR/>
 * 
 * @author MCH；Date：2008-06-18；<BR/>
 *
 * @param <T>
 */
public class HttpRequestHandler<T> extends AbstractHandler<T> {

	private String userAgent;
	private String requestUrl;
	private String charset;

	private Map<?, ?> requestParam;
	private Map<?, ?> requestHeader;

	private int statusCode;
	private String content;

	private HttpResponse httpResponse;

	private CloseableHttpClient httpClient;

	/**
	 * 
	 * @param requestUrl
	 *            ：请求URL
	 * @param requestParam
	 *            ：请求参数
	 * @param requestHeader
	 *            ：请求头信息
	 * @param userAgent
	 */
	public HttpRequestHandler(String requestUrl, Map<?, ?> requestParam, Map<?, ?> requestHeader, String userAgent) {
		this(requestUrl, requestParam, requestHeader, userAgent, Consts.UTF_8.toString());
	}

	public HttpRequestHandler(String requestUrl, Map<?, ?> requestParam, Map<?, ?> requestHeader, String userAgent, String charset) {
		super();
		this.userAgent = userAgent;
		this.requestUrl = requestUrl;
		this.charset = charset;
		this.requestParam = requestParam;
		this.requestHeader = requestHeader;
		initHttpClient();
	}

	private void initHttpClient() {
		HttpClientBuilder clientBuilder = HttpClientBuilder.create();
		clientBuilder.setUserAgent(userAgent);
		httpClient = clientBuilder.build();
	}

	@Override
	public T handle() throws Exception {
		try {
			// 1、构建 HttpPost 请求对象
			HttpPost post = buildHttpPost();

			// 2、执行请求，并返回响应对象
			httpResponse = httpClient.execute(post);

			// 3、通过响应对象获取响应消息实体
			HttpEntity entity = httpResponse.getEntity();

			statusCode = httpResponse.getStatusLine().getStatusCode();

			content = IOUtils.toString(entity.getContent(), "UTF-8");
			EntityUtils.consume(entity);// 消灭响应消息实体
		} finally {
			httpClient.close();
		}

		return null;
	}

	protected HttpPost buildHttpPost() throws UnsupportedEncodingException {
		// 1、设置Post请求，及请求地址
		HttpPost post = new HttpPost(requestUrl);
		post.setProtocolVersion(HttpVersion.HTTP_1_1);

		setHttpPostHeader(post);

		// 2、设置参数键值
		List<NameValuePair> paraList = buildNameValuePair(requestParam);

		// 3、设置提交编码
		post.setEntity(new UrlEncodedFormEntity(paraList, charset));

		// 设置请求和传输超时时间
		RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(10000).setConnectTimeout(10000).setConnectionRequestTimeout(5000).build();
		post.setConfig(requestConfig);

		return post;
	}

	private void setHttpPostHeader(HttpPost post) {
		if (requestHeader == null || requestHeader.isEmpty()) {
			return;
		}

		String[] keys = requestHeader.keySet().toArray(new String[0]);
		for (int i = 0, len = keys.length; i < len; i++) {
			String key = keys[i];
			post.addHeader(key, requestHeader.get(key).toString());
		}
	}

	public List<NameValuePair> buildNameValuePair(Map<?, ?> paraMap) {
		if (paraMap == null || paraMap.isEmpty()) {
			return null;
		}

		List<NameValuePair> list = new ArrayList<NameValuePair>();
		String[] keys = paraMap.keySet().toArray(new String[0]);
		for (int i = 0, len = keys.length; i < len; i++) {
			String kkey = keys[i];
			list.add(new BasicNameValuePair(kkey, tool().toStr(paraMap.get(kkey))));
		}

		return list;
	}

	public HttpResponse getHttpResponse() {
		return httpResponse;
	}

	public int getStatusCode() {
		return statusCode;
	}

	public String getContent() {
		return content;
	}
}
